#ifndef BSPLINE_H
#define BSPLINE_H

#include "utils.h"
#include <stdlib.h>
#include <vector>
#include <qobject.h>

class BSplineCurve : public QObject
{
	Q_OBJECT
public:

	// Constructor/destructor 
	BSplineCurve();
	~BSplineCurve();

	// Getters for order and increment
	int getOrder();
	double getIncrement();

	// Methods to do with geometry
	BSplineSnapshot* getGeometry(double u);
	std::vector<Point3D*>* getCurvePoints();

	// Control point operations
	std::vector<Point3D*>* getControlPoints();
	bool isPointSelected();
	bool isSelectedPoint(const Point3D* point);
	void addControlPoint(Point3D& at);
	void removeControlPoint(Point3D& reference);
	bool selectControlPoint(Point3D& reference);
	void moveSelectedPoint(Vector3D& delta);
    void movePoint(Point3D* ref, double x, double y, double z);
	void deselectCurrentPoint();

signals:

	// None so far
	void dataDirty(void);

public slots:

	void setOrder(int order);
	void setIncrement(double increment);

protected:

	// Nothing here so far

private:

	// Class attributes
	bool   _isDataDirty;
	bool   _majorChange;
	bool   _pointMoved;
	int    _movedPointIndex;
	int    _order;
	int    _selectedIndex;
	double _increment;
    
	std::vector<Point3D*>* _controlPoints;
	std::vector<double>*  _knotSequence;
    
	// Helper methods
	void initializeAttributes();
    
	std::vector<Point3D*>* _latestCurve;
	std::vector<BSplineSnapshot*>* _latestGeometries;

	int getDelta(double u);
	void updateKnotSequence();
	Point3D* getCurvePoint(double u, BSplineSnapshot* geometry);
	int findNearestPointIndex(const Point3D& reference, Vector3D& smallestDelta);
};

#endif
